package org.ouwh.oowiki.http;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.Properties;

import javax.management.MBeanServer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import org.eclipse.jetty.webapp.WebAppContext;
import org.ouwh.fw.model.data.Struct;
import org.ouwh.fw.model.service.Service;

public class HttpService extends Service {
	private static Log log = LogFactory.getLog(HttpService.class);
	private static final String LOGGER_NAME = "logger-name";
	private static final String INVOKE_HANDLER = "invoke-handler";
	private static final String LISTEN_PORT = "listen-port";
	private static final String DEBUG_HTTP = "debug-http";
	private static final String RESOURCE_BASE = "resource-base";
	private static final String CONTEXT_PATH = "context-path";
	private int listenPort;
	private String invokeHandler;
	private String jettyLoggerName;
	private String isDebugHttp;
	private MBeanContainer mBeanContainer;
	private String resourceBase;
	private String contextPath;
	private Server webServer;

	@Override
	protected void dumpToStruct(Struct struct) {
		struct.addData(LISTEN_PORT, listenPort);
		struct.addData(INVOKE_HANDLER, invokeHandler);
		struct.addData(LOGGER_NAME, jettyLoggerName);
		struct.addData(DEBUG_HTTP, isDebugHttp);
		struct.addData(RESOURCE_BASE, resourceBase);
		struct.addData(CONTEXT_PATH, contextPath);
	}

	@Override
	protected void init(Properties properties) {
		listenPort = Integer.parseInt(properties.getProperty(LISTEN_PORT));
		invokeHandler = properties.getProperty(INVOKE_HANDLER);
		jettyLoggerName = properties.getProperty(LOGGER_NAME);
		isDebugHttp = properties.getProperty(DEBUG_HTTP);
		resourceBase = properties.getProperty(RESOURCE_BASE);
		contextPath = properties.getProperty(CONTEXT_PATH);
	}

	@Override
	protected void reset(Properties properties) throws Exception {
		int tmpListenPort = Integer.parseInt(properties.getProperty(LISTEN_PORT));
		String tmpInvokeHandler = properties.getProperty(INVOKE_HANDLER);
		jettyLoggerName = properties.getProperty(LOGGER_NAME);
		isDebugHttp = properties.getProperty(DEBUG_HTTP);
		String tmpResourceBase = properties.getProperty(RESOURCE_BASE);
		String tmpContextPath = properties.getProperty(CONTEXT_PATH);

		if ((tmpListenPort != listenPort) || (!tmpInvokeHandler.equals(invokeHandler))
				|| (!tmpResourceBase.equals(resourceBase)) || (!tmpContextPath.equals(contextPath))) {
			listenPort = tmpListenPort;
			invokeHandler = tmpInvokeHandler;
			resourceBase = tmpResourceBase;
			contextPath = tmpContextPath;
			stop();
			start();
		}
	}

	@Override
	protected void shutdown() throws Exception {
		log.info("HTTP Server stopping...");
		if (webServer != null) {
			webServer.stop();
			webServer.join();
			webServer.getContainer().removeEventListener(mBeanContainer);
			webServer = null;
		}
		if (mBeanContainer != null) {
			mBeanContainer.stop();
			mBeanContainer = null;
		}
		log.info("HTTP Server stopped.");
	}

	@Override
	protected void startup() throws Exception {
		log.info("HTTP Server starting...");
		System.setProperty("org.eclipse.jetty.util.log.class",
				jettyLoggerName == null ? "org.ouwh.oowiki.http.JettyLog" : jettyLoggerName);
		System.setProperty("org.ouwh.oowiki.http.jetty.DEBUG", isDebugHttp);
		org.eclipse.jetty.util.log.Log.initialized();
		if (mBeanContainer == null) {
			MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
			mBeanContainer = new MBeanContainer(mBeanServer);
		}

		if (webServer == null) {
			webServer = new Server(listenPort);

//			WebAppContext webapp = new WebAppContext();
//			webapp.setContextPath(contextPath);
//			webapp.setDefaultsDescriptor(resourceBase + File.separator + "WEB-INF" + File.separator + "web.xml");
//			webapp.setResourceBase(resourceBase);

			Class<?> hClass = Class.forName(invokeHandler);
			Handler tmpInvokeHandler = (Handler) hClass.newInstance();

			ResourceHandler resourceHandler = new ResourceHandler();
			resourceHandler.setResourceBase(resourceBase);
			resourceHandler.setDirectoriesListed(false);

			HandlerList handlers = new HandlerList();
			handlers.setHandlers(new Handler[] { resourceHandler, tmpInvokeHandler });

			UriAccessHandler uriAccessHandler = new UriAccessHandler();
			uriAccessHandler.setHandler(handlers);

			webServer.setHandler(uriAccessHandler);
			webServer.getContainer().addEventListener(mBeanContainer);
		}
		if (!mBeanContainer.isRunning()) {
			mBeanContainer.start();
		}
		if (!webServer.isRunning()) {
			webServer.start();
		}
		log.info("HTTP Server started.");
	}

}
